// src/parsers/universal/babelAstUtils.ts
import generate from '@babel/generator';
import * as t from '@babel/types';
import type { NodeSemanticType } from '@/models/universalFlow';

// --- Configuration for babelGenerator ---
const generatorOptions = { // <<< 已修正：const 在新行开始
    comments: false, // Ignore comments
    compact: true,   // Minimize whitespace
    jsescOption: { minimal: true } // Minimal escape sequences
};

/**
 * Helper to safely get an Identifier name, handling patterns.
 * @param id The Babel LVal node (Identifier, Pattern, etc.).
 * @returns The identifier name as a string, or null if it's complex or not identifiable.
 */
export function getIdentifierName(id: t.LVal | null | undefined): string | null {
    if (!id) return null;
    if (t.isIdentifier(id)) {
        return id.name;
    }
    // Handle common destructuring patterns simply - return null as they don't have a single name
    if (t.isArrayPattern(id)) return null;
    if (t.isObjectPattern(id)) return null;
    if (t.isAssignmentPattern(id)) return getIdentifierName(id.left); // Recurse left side of assignment
    // Handle RestElement correctly by trying to get name from its argument
    if (t.isRestElement(id) && id.argument) {
        // Ensure the argument is treated as LVal if needed for recursion, though RestElement argument type might vary
        const argName = getIdentifierName(id.argument as t.LVal); // Recurse into argument, cast might be needed depending on exact types allowed
        return argName ? `...${argName}` : null;
    }

    // For MemberExpression in assignment targets, return null as it needs generation
    if (t.isMemberExpression(id)) return null;

    // Note: t.LVal includes more complex types like TSAs Expressions, which we won't specifically handle here.
    return null; // Indicate complexity or unhandled type
}

/**
 * Extracts the value from various Literal Babel AST nodes.
 * Returns undefined if the node is not a recognized literal type or value is invalid.
 */
export function getLiteralValue(node: t.Node): string | number | boolean | null | undefined | bigint | RegExp {
  if (!node) return undefined;
  if (t.isStringLiteral(node) || t.isNumericLiteral(node) || t.isBooleanLiteral(node)) {
      return node.value;
  }
  if (t.isBigIntLiteral(node)) {
      return BigInt(node.value); // Return as BigInt
  }
  if(t.isRegExpLiteral(node)) {
      // Reconstruct RegExp object
      try { return new RegExp(node.pattern, node.flags); }
      catch(e) { console.error("Error creating RegExp:", e); return undefined; }
  }
  // NullLiteral has no value property
  if (t.isNullLiteral(node)) return null;
  // Add other literal types if necessary (e.g., DecimalLiteral)
  return undefined;
}

/**
 * Determines a more specific semantic type based on the Babel node type.
 * Version 2: More granular types for expressions.
 */
export function getSemanticTypeV2(node: t.Node): NodeSemanticType {
    if (t.isProgram(node)) return 'root';
    if (t.isBlockStatement(node)) return 'programBody';
    if (t.isObjectExpression(node)) return 'object';
    if (t.isArrayExpression(node)) return 'array';
    if (t.isNullLiteral(node)) return 'value'; // Null is a value
    if (t.isLiteral(node)) return 'value'; // Other literals are values
    if (t.isIdentifier(node)) return 'variableReference';
    if (t.isCallExpression(node)) return 'functionCall';
    if (t.isMemberExpression(node)) return 'memberExpression';
    if (t.isBinaryExpression(node) || t.isLogicalExpression(node)) return 'binaryExpression';
    if (t.isUnaryExpression(node)) return 'unaryExpression';
    if (t.isConditionalExpression(node)) return 'conditionalExpression';
    if (t.isTemplateLiteral(node)) return 'templateLiteral';
    if (t.isNewExpression(node)) return 'newExpression';
    if (t.isFunction(node)) return 'value'; // Function definitions treated as values for now
    if (t.isExportDefaultDeclaration(node) || t.isExportNamedDeclaration(node)) return 'exportDeclaration';
    if (t.isImportDeclaration(node)) return 'importDeclaration';
    if (t.isIfStatement(node)) return 'conditional';
    if (t.isForStatement(node) || t.isForInStatement(node) || t.isForOfStatement(node) || t.isWhileStatement(node) || t.isDoWhileStatement(node)) return 'loop';
    // Add more specific TS types as needed
    // if (t.isTSModuleDeclaration(node)) return 'module';

    // console.warn('[getSemanticTypeV2] Unmapped node type:', node.type);
    return 'unknown'; // Fallback for unmapped types
}

/**
 * Retrieves the source location (start/end line/column) of a Babel node.
 */
export function getNodeLocation(node: t.Node): t.SourceLocation | null {
    return node.loc || null;
}

/**
 * Helper function to generate a concise string representation of a Babel Node.
 * Useful for displaying complex keys or callee expressions.
 * @param node The Babel AST node.
 * @returns A string representation of the node's code.
 */
export function generateNodeCode(node: t.Node | null | undefined): string {
    if (!node) return '';
    try {
        // @ts-ignore - Babel generator types might be slightly off or expect specific node types
        const output = generate(node, generatorOptions);
        return output.code;
    } catch (error) {
        console.error(`[generateNodeCode] Error generating code for node type ${node?.type}:`, error);
        return `[Error Generating ${node?.type}]`;
    }
}